package net.gazhi.delonix.core.dao;

import java.io.Serializable;
import java.sql.Date;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

/**
 * 封装基本的 DAO 操作
 * 
 * @author Jeffrey Lin
 * 
 */
public class Dao {

	private SessionFactory sessionFactory;

	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	public Session getSession() {
		return getSessionFactory().getCurrentSession();
	}

	@SuppressWarnings("unchecked")
	public <T> T get(Class<T> entityClass, Serializable id) {
		return (T) getSession().get(entityClass, id);
	}

	public void save(Object entity) {
		getSession().save(entity);
	}

	public void saveAll(Collection<?> entities) {
		Session session = this.getSession();
		for (Object e : entities) {
			session.save(e);
		}
	}

	public void saveOrUpdateAll(Collection<?> entities) {
		Session session = this.getSession();
		for (Object e : entities) {
			session.saveOrUpdate(e);
		}
	}

	public void update(Object entity) {
		getSession().update(entity);
	}

	public void saveOrUpdate(Object entity) {
		getSession().saveOrUpdate(entity);
	}

	public void delete(Object eitity) {
		getSession().delete(eitity);
	}

	public Criteria createCriteria(Class<?> clazz) {
		try {
			return getSession().createCriteria(clazz);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public Criteria createCriteria(Class<?> clazz, String ailias) {
		try {
			return getSession().createCriteria(clazz, ailias);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public SQLQuery createSQLQuery(String sql) {
		return getSession().createSQLQuery(sql);
	}

	public void flushSession() {
		this.getSession().flush();
	}

	/**
	 * 执行批处理HQL语句.如 之间insert, update, delete等.
	 */
	public int execteBulk(final String hql, final Object... paramlist) {
		Query query = getSession().createQuery(hql);
		setParameters(query, paramlist);
		Object result = query.executeUpdate();
		return result == null ? 0 : ((Integer) result).intValue();
	}

	/**
	 * 执行批处理SQL语句.如 之间insert, update, delete等.
	 */
	public int execteNativeBulk(final String natvieSQL, final Object... paramlist) {
		Query query = getSession().createSQLQuery(natvieSQL);
		setParameters(query, paramlist);
		Object result = query.executeUpdate();
		return result == null ? 0 : ((Integer) result).intValue();
	}

	private void setParameters(Query query, Object[] paramlist) {
		if (paramlist != null) {
			for (int i = 0; i < paramlist.length; i++) {
				if (paramlist[i] instanceof Date) {
					query.setTimestamp(i, (Date) paramlist[i]);
				} else {
					query.setParameter(i, paramlist[i]);
				}
			}
		}
	}

	/**
	 * 分页查找
	 * 
	 * @param query
	 * @param pageInfo
	 * @param order
	 *            每个分页查找都要求至少一个排序字段
	 * @param orders
	 *            更多排序字段
	 * @return
	 */
	public List<?> listPage(Criteria query, PageInfo pageInfo, Order order, Order... orders) {
		// 查询总记录数
		query.setProjection(Projections.rowCount());
		Long rowCount = (Long) query.uniqueResult();
		if (rowCount == null || rowCount == 0) {
			return new ArrayList<Object>();
		}
		pageInfo.setRsCount(rowCount);

		// 分页查询
		query.setProjection(null);
		query.setMaxResults(pageInfo.getPageSize());
		query.setFirstResult(pageInfo.getStartRsIndex());
		query.setResultTransformer(Criteria.ROOT_ENTITY);
		if (order != null) {
			query.addOrder(order);
		}
		for (Order order1 : orders) {
			query.addOrder(order1);
		}
		return query.list();
	}

	public List<?> listPageByDistinctId(Criteria pageQuery, Criteria entityQuery, PageInfo pageInfo, Order order, Order... orders) {

		// 查找总记录数
		pageQuery.setProjection(Projections.countDistinct("id"));
		pageInfo.setRsCount((Long) pageQuery.uniqueResult());

		// 设置排序
		if (order != null) {
			pageQuery.addOrder(order);
			entityQuery.addOrder(order);
		}
		for (Order order1 : orders) {
			pageQuery.addOrder(order1);
			entityQuery.addOrder(order1);
		}

		// 分页返回ID列表
		pageQuery.setMaxResults(pageInfo.getPageSize());
		pageQuery.setFirstResult(pageInfo.getStartRsIndex());
		pageQuery.setProjection(Projections.groupProperty("id"));
		List<?> ids = pageQuery.list();

		// 根据ID列表查找实体对象列表
		if (ids.size() == 0) {
			return new ArrayList<Object>();
		}
		entityQuery.add(Restrictions.in("id", ids));
		return entityQuery.list();
	}
}
